#ifndef LIB_H
#define LIB_H

#include <string>
#include <iomanip>
#include <vector>

#include "debugstreams.h"

#include <boost/lexical_cast.hpp>

using namespace std;

/** @addtogroup Utilitaires
 *  @{
 */

/**
 * Gestion des compétences non martiales disponibles pour une classe donnée.
 */
enum TypeClasse { Toutes,      /**< Accessible à toutes les classes */
		  Combattants, /**< Pour les guerriers, paladins et rôdeurs */
		  Magiciens,   /**< Pour les mages et spécialistes */
		  Pretres,     /**< Pour les clercs et druides */
		  Roublards    /**< Pour les bardes et voleurs */
};

/**
 * Gestion des compétences non-martiales. On associe le nom de la
 * compétence diverse avec son coût, sa valeur de base, les éventuels
 * traits associés (un 255 signifie qu'il n'y a pas de tel trait), et
 * le type de classe autorisé.
 */
struct ListNonMart
{
  string Comp;          /**< Nom de la compétence non-martiale */
  unsigned int Cout;    /**< Cout de la compétence */
  unsigned int Valeur;  /**< Valeur de base */
  unsigned int Trait1;  /**< Trait associé 1 */
  unsigned int Trait2;  /**< Trait associé 2 */
  TypeClasse Cl_Admise; /**< Classe autorisée */
};

int puissance(int a, unsigned int b);

unsigned int digit(const int& a, const int& b);

/** Convertit un nombre quelconque en chaîne de caractère.
 * On utilise lexical_cast (librairie boost) pour aller plus vite
 * qu'en utilisant un stringstream.
 *
 * @param type nombre à convertir.
 * @return la chaîne de caractère correspondante.
 */
template <typename T>
string ecrireString(const T& type)
{
  return boost::lexical_cast<string>(type);
}

/** Permet la lecture de n'importe quel nombre depuis une chaîne de
 * caractère.
 * A nouveau on utilise lexical_cast (boost) pour se simplifier la
 * vie. Ici il faut faire attention au fait que la conversion peut mal
 * se passer, donc on a une structure try - catch.
 *
 *
 * @param str chaîne de caractère à lire.
 * @param type variable dans laquelle le nombre sera stocké.
 * @return \e true si tout s'est bien passé, \e false si une exception
 * est levée.
 */
template <typename T>
bool lireString(const string& str, T& type)
{
  try
    {
      type = boost::lexical_cast<T>(str);
    }
  catch(boost::bad_lexical_cast& e)
    {
      error() << e.what() << "** " << str << " **" << endl;
      return false;
    }
  return true;
}

unsigned int demanderUnsigned(const string& question);

unsigned int demanderUnsignedBorne(const string& question,
				   const unsigned int& min,
				   const unsigned int& max);

string afficheAccent(const string& brut);

bool safePushBack(vector<unsigned int> *ptr, const unsigned int& valeur);

bool safePushBack(vector<unsigned int> *ptr, const unsigned int& valeur,
		    vector<unsigned int>& sauter);

void gererEspacesBlancs(char* tab[], int& nbr, vector<string>& retour);

bool lireVectorUInt(const string& donnees, vector< unsigned int> *vec);

void determinerScoresAjustes(const string& race, const unsigned int& dext,
			     vector< int >*& ptr);

void obtenirScoresBase(const unsigned int& niveau, vector<unsigned int>*& ptr);

/** @} */

#endif
